#include <stdio.h>
#include "l8w8jwt/encode.h"
#include "l8w8jwt/decode.h"
#include <string.h>
#include "jwt.h"

//**头部（Header）和载荷（Payload）**分别用 Base64Url 编码。
//编码后的头部和编码后的载荷用点号（.）连接起来，形成签名前的数据字符串
//base64UrlEncode(header) + "." + base64UrlEncode(payload)
//使用指定的 HMAC 算法（例如 HS512），将上一步生成的字符串和密钥一起进行哈希运算，生成签名。
//signature = HMACSHA512(
// base64UrlEncode(header) + "." + base64UrlEncode(payload),
//    secret_key)
//  完整的jwt：
//  JWT = base64UrlEncode(header) + "." + base64UrlEncode(payload) + "." + base64UrlEncode(signature)
char* generate_jwt(const char* sub, const char* iss, const char* aud, \
                   const char* secret_key, int exp_duration_seconds) {   
    char* jwt=NULL ; // 最终要生成的 jwt
    size_t jwt_length =0; // 长度

    struct l8w8jwt_encoding_params params; // 结构体

    // 初始化结构体
    l8w8jwt_encoding_params_init(&params);

    params.alg = L8W8JWT_ALG_HS512; // 生成的算法

    //描述jwt令牌的信息
    params.sub = (char*)sub; // 用户（JWT 所面向的用户），通常用于唯一标识 JWT 的主体。这个主体可以是用户 ID 或用户名等
    params.iss = (char*)iss; // 签发者（JWT 的签发者），签发者可以是认证服务器的名称或标识符。
    params.aud = (char*)aud; //接收 JWT 的实体。接收方可以是应用程序或服务的标识符。



    params.iat = l8w8jwt_time(NULL); // 签发时间
    params.exp = l8w8jwt_time(NULL) + exp_duration_seconds; // 过期时间:10分钟

    params.secret_key = (unsigned char*)secret_key; // 密钥：用于生成签名,可以自己设定
    params.secret_key_length = strlen((const char*)params.secret_key); // 密钥长度

    params.out = &jwt; //用于存储生成的 JWT 字符串
    params.out_length = &jwt_length; // 用于存储生成的 JWT 字符串的长度。

    int r = l8w8jwt_encode(&params); // 生成 JWT

    //  printf("\n l8w8jwt example HS512 token : %s \n", r == L8W8JWT_SUCCESS ? jwt_out : "(encode failure)");

    //  l8w8jwt_free(jwt); // 释放生成的 JWT

    int result = l8w8jwt_encode(&params);

    if (r != L8W8JWT_SUCCESS) {
        // 如果生成失败，释放内存并返回 NULL
        if (jwt) {
            l8w8jwt_free(jwt);
        }
        return NULL;
    }

    return jwt;
}


//解码函数
int verify_jwt(const char* jwt, const char* key, const char* expected_iss, const char* expected_sub){
    struct l8w8jwt_decoding_params params;//用于存储解码过程的参数。
    l8w8jwt_decoding_params_init(&params);//初始化

    params.alg = L8W8JWT_ALG_HS512;//解码算法，需要与 JWT 的签名算法一致。

    params.jwt = (char*)jwt;//指定解码函数要处理的 JWT 字符串。
    params.jwt_length = strlen(jwt);//告诉解码函数 JWT 的长度，以正确处理 JWT 字符串。

    params.verification_key = (unsigned char*)key;// 签名验证密钥
    params.verification_key_length = strlen(key);//长度

    params.validate_iss = (char*)expected_iss;// 设置 params.validate_iss 为预期的签发者（iss）值。
    params.validate_sub = (char*)expected_sub; //设置 params.validate_sub 为预期的用户（sub）值。

    //设置是否验证 JWT 的过期时间（exp）。
    //0 表示不验证过期时间。如果需要验证过期时间，通常会设置为1。
    params.validate_exp = 1;

    //允许 JWT 在过期时间后宽限 60 秒。如果 JWT 的过期时间晚于当前时间加上容忍度，则视为有效。
    params.exp_tolerance_seconds =0;

    //1 表示验证签发时间。如果设置为 0，则不验证。
    params.validate_iat = 1;
    //延后60s
    params.iat_tolerance_seconds = 0;


    // 声明一个枚举变量 validation_result，用于存储 JWT 验证结果。
    enum l8w8jwt_validation_result validation_result;

    //decode_result 存储函数的返回值，通常为一个状态码，表示解码是否成功。
    //validation_result 存储详细的验证结果，指示 JWT 是否有效，以及任何验证失败的原因。
    int decode_result = l8w8jwt_decode(&params,&validation_result,NULL,NULL);

     if (decode_result == L8W8JWT_SUCCESS && validation_result == L8W8JWT_VALID)
    {
        return 1; // JWT 验证成功
    }
    else
    {
        return 0; // JWT 验证失败
    }
}
